//g++ -fsanitize=address -O0 -g -lasan ConsoleApplication1.cpp
#define _CRT_SECURE_NO_WARNINGS

#include <assert.h>

//#if defined(_WIN32) && defined(_DEBUG)
//#include <vld.h>
//#endif

#define FMT_HEADER_ONLY
#define FMT_UNICODE 0
#include <fmt/core.h>
#include <fmt/ranges.h>

#include "SyncBox.hpp"

using _TIn  = std::tuple<std::string, std::string>;
using _TOut = std::tuple<int, std::string, std::string>;

int main()
{
    std::function<_TOut(_TIn&)> do_work = [&](_TIn& in) {
        _TOut tout = std::make_tuple(200, "application/json", fmt::format("{{\"id\":{}}}", std::get<0>(in)));
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        return std::move(tout);
    };

    Sync<_TIn, _TOut> sync(do_work);

    for (int i = 0; i < 10; i++)
    {
        std::thread([&](int idx) {
            auto on_send = [&]() {
                std::string s  = fmt::format("{}", idx + 100);
                _TIn in = std::make_tuple(s, std::string("123"));
                return std::move(in);
            };
            auto on_timeout = [&](_TIn& in) {
                std::string a = std::get<0>(in);
                std::string b = std::get<1>(in);
                fmt::println("timeout. {}, {}", a, b);
            };
            auto on_receive = [&](_TIn& in, _TOut& TOut) {
                int         status       = std::get<0>(TOut);
                std::string content_type = std::get<1>(TOut);
                std::string body         = std::get<2>(TOut);

                fmt::print("recv < [{}] - {} {}\r\n", status, content_type, body);
            };

            sync.transmit(1000, on_send, on_receive, on_timeout);
        }, i).detach();
    };

    std::this_thread::sleep_for(std::chrono::milliseconds(10000));
}
